﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Crawler.Framework;
using Crawler.Model.SystemDefault;
using Newtonsoft.Json;
using Crawler.Core.Analyzer;
using System.Data;
using MySql.Data.MySqlClient;
using NPOI.HSSF.UserModel;
using System.IO;

namespace Crawler.App.Manager.Controllers
{
    public class CollectInfoConfigController : Controller
    {
        private readonly MyDbContext _context;
        private readonly AnalyzerManager analyzerManager;

        public CollectInfoConfigController(MyDbContext context, AnalyzerManager analyzerManager)
        {
            _context = context;
            this.analyzerManager = analyzerManager;
        }

        // GET: CollectInfoConfigModels
        public async Task<IActionResult> Index()
        {
            return View();
        }

        public async Task<IActionResult> List(int page,int limit)
        {
            var count = await _context.CollectInfoConfigs.CountAsync();
            var data = await _context.CollectInfoConfigs.Skip((page - 1) * limit).Take(limit).ToListAsync();
            return Json(new {code=0,msg="",count,data});
        }


        // GET: CollectInfoConfigModels/Create
        public IActionResult Create()
        {
            ViewBag.Analyzers = analyzerManager.GetAnalyzerInfos();
            return View();
        }

        // POST: CollectInfoConfigModels/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Name,StartUrl,FilterHost,Encoding,Depth,AnalyzeType,PluginPath,LatestCollectTime,CollectorStatus,WorkStatus,ID")] CollectInfoConfigModel collectInfoConfigModel)
        {
            if (ModelState.IsValid)
            {
                collectInfoConfigModel.LatestCollectTime = DateTime.Now;
                _context.Add(collectInfoConfigModel);
                await _context.SaveChangesAsync();
                return Json(new { code = 0, msg = ""});
            }
            return Json(new { code = 1, msg = $"数据验证失败:{JsonConvert.SerializeObject(ModelState.Values)}" });
        }

        // GET: CollectInfoConfigModels/Edit/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return Json(new { code = 1, msg = "id为空" });
            }

            var collectInfoConfigModel = await _context.CollectInfoConfigs.FindAsync(id);
            if (collectInfoConfigModel == null)
            {
                return Json(new { code = 1, msg = "找不到指定对象" });
            }
            return  Json(new { code = 0, msg = "",data= collectInfoConfigModel }); ;
        }

        // GET: CollectInfoConfigModels/Edit/5
        public async Task<IActionResult> Edit()
        {
            ViewBag.Analyzers = analyzerManager.GetAnalyzerInfos();
            return View();
        }


        // POST: CollectInfoConfigModels/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Name,StartUrl,FilterHost,Encoding,Depth,AnalyzeType,PluginPath,LatestCollectTime,CollectorStatus,WorkStatus,ID")] CollectInfoConfigModel collectInfoConfigModel)
        {
            if (id != collectInfoConfigModel.ID)
            {
                return Json(new { code = 1, msg = "找不到指定对象" });
            }

            if (ModelState.IsValid)
            {
                try
                {
                    collectInfoConfigModel.LatestCollectTime = DateTime.Now;
                    _context.Update(collectInfoConfigModel);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!CollectInfoConfigModelExists(collectInfoConfigModel.ID))
                    {
                        return Json(new { code = 1, msg = "找不到指定对象" });
                    }
                    else
                    {
                        throw;
                    }
                }
                return Json(new { code = 0, msg = "" });
            }
            return Json(new { code = 1, msg = $"数据验证失败:{JsonConvert.SerializeObject(ModelState.Values)}" });
        }

        // POST: CollectInfoConfigModels/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Delete(int[] id)
        {
            if (id == null)
            {
                return Json(new { code = 1, msg = "id为空" });
            }
            var collectInfoConfigModels = await _context.CollectInfoConfigs.Where(c=> id.Contains(c.ID)).ToListAsync();

            collectInfoConfigModels.ForEach(c =>
            {
                _context.CollectInfoConfigs.Remove(c);
            });
            await _context.SaveChangesAsync();
            return Json(new { code = 0, msg = "", data = collectInfoConfigModels });
        }

        private bool CollectInfoConfigModelExists(int id)
        {
            return _context.CollectInfoConfigs.Any(e => e.ID == id);
        }

        public async Task<IActionResult> Result(int configId,string analyzerFullName)
        {
            ViewBag.Fields = analyzerManager.GetAnalyzerInfoFullName(analyzerFullName).Fields;
            return View();
        }
        public async Task<IActionResult> ResultList(int configId, string analyzerFullName, int page, int limit)
        {
            var info = analyzerManager.GetAnalyzerInfoFullName(analyzerFullName);
            int count;
            DataTable data = new DataTable();

            foreach (var item in info.Fields)
            {
                data.Columns.Add(item, typeof(string));
            }
            using (var conn = _context.Database.GetDbConnection())
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = $"select count(0) from {info.TableName} where configId='{configId}'";
                    cmd.CommandType = System.Data.CommandType.Text;
                    count = Convert.ToInt32(cmd.ExecuteScalar());
                }

                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = $"select {string.Join(",", info.Fields)} from {info.TableName}  where configId='{configId}' limit {(page - 1) * limit},{limit}";
                    cmd.CommandType = System.Data.CommandType.Text;
                    var reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        var row = data.NewRow();
                        foreach (var item in info.Fields)
                        {
                            row[item] = reader[item];
                        }
                        data.Rows.Add(row);
                    }
                }

            }

            return Json(new { code = 0, msg = "", count, data });
        }

        public void Export(int configId, string analyzerFullName)
        {
            var config = _context.CollectInfoConfigs.Where(e => e.ID == configId).FirstOrDefault();
            var info = analyzerManager.GetAnalyzerInfoFullName(analyzerFullName);

            using (var conn = _context.Database.GetDbConnection())
            {
                conn.Open();

                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = $"select {string.Join(",", info.Fields)} from {info.TableName}  where configId='{configId}' ";
                    cmd.CommandType = System.Data.CommandType.Text;
                    var reader = cmd.ExecuteReader();


                    var workBook = new HSSFWorkbook();
                    var sheet = workBook.CreateSheet("sheet0");
                    var stream = new MemoryStream();
                    var rowIndex = 0;
                    while (reader.Read())
                    {
                        var row = sheet.CreateRow(rowIndex++);
                        for (int i = 0; i < info.Fields.Count(); i++)
                        {
                            var cell = row.CreateCell(i);
                            var value = reader[info.Fields[i]];
                            cell.SetCellValue(value == null ? "" : value.ToString());
                        }
                    }
                    workBook.Write(stream);
                    stream.Flush();
                    stream.Position = 0;

                    HttpContext.Response.ContentType = "octet-stream";// resources.ResourcesMime;
                    HttpContext.Response.Headers["Content-Disposition"] = $"filename=\"{System.Web.HttpUtility.UrlEncode($"采集结果-{config.Name}")}.xls\"";

                    byte[] buffer = new byte[stream.Length];
                    stream.Read(buffer, 0, buffer.Length);
                    HttpContext.Response.Body.Write(buffer, 0, buffer.Length);
                    HttpContext.Response.Body.Flush();
                }

            }
        }
        [HttpPost]
        public async Task<IActionResult> Clear(int configId, string analyzerFullName)
        {
            var config = _context.CollectInfoConfigs.Where(e => e.ID == configId).FirstOrDefault();
            var info = analyzerManager.GetAnalyzerInfoFullName(analyzerFullName);

            using (var conn = _context.Database.GetDbConnection())
            {
                conn.Open();

                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = $"delete from {info.TableName}  where configId='{configId}' ";
                    cmd.CommandType = System.Data.CommandType.Text;
                    cmd.ExecuteNonQuery();
                }

            }
            return Json(new { code = 0, msg = ""});
        }
    }
}
